package com.sky.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ejlchina.searcher.BeanSearcher;
import com.ejlchina.searcher.SearchResult;
import com.ejlchina.searcher.operator.Contain;
import com.ejlchina.searcher.operator.Equal;
import com.ejlchina.searcher.operator.InList;
import com.ejlchina.searcher.util.MapUtils;
import com.sky.common.Attachment;
import com.sky.common.File;
import com.sky.common.FileCommon;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.DishDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.SetmealDish;
import com.sky.exception.ServiceException;
import com.sky.mapper.AttachmentMapper;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.service.DishService;
import com.sky.utils.BeanCopyUtil;
import com.sky.utils.DateUtils;
import com.sky.utils.StringUtils;
import com.sky.vo.DishVO;
import com.sky.web.page.TableSupport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Author tzl
 * @Date 2023-07-07 18:29:18  星期五
 * @Description: 菜品管理业务层实现类
 */
@Slf4j
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private BeanSearcher beanSearcher;

    @Autowired
    private FileCommon fileCommon;

    @Autowired
    private AttachmentMapper attachmentMapper;

    @Override
    public SearchResult<DishVO> selectDishList(DishDTO dto) {
        Map<String, Object> build = MapUtils.builder()
                .page(TableSupport.buildPageRequest().getPageNum(),
                        TableSupport.buildPageRequest().getPageSize())
                .field(DishVO::getName,dto.getName()).op(Contain.class)
                .field(DishVO::getCategoryId,dto.getCategoryId()).op(Equal.class)
                .field(DishVO::getStatus,dto.getStatus()).op(Equal.class)
                .orderBy(DishVO::getCreateTime).desc()
                .build();
        return beanSearcher.search(DishVO.class, build);
    }

    /**
     * 菜品查询
     * @param dto 查询信息
     * @return
     */
    @Override
    public List<DishVO> selectDishListALl(DishDTO dto) {
        Map<String, Object> build = MapUtils.builder()
                .field(DishVO::getName,dto.getName()).op(Contain.class)
                .field(DishVO::getCategoryId,dto.getCategoryId()).op(Equal.class)
                .field(DishVO::getStatus,dto.getStatus()).op(Equal.class)
                .orderBy(DishVO::getCreateTime).desc()
                .build();
        return beanSearcher.searchAll(DishVO.class, build);
    }

    /**
     * 查询起售中的所有菜品
     */
    @Override
    public List<DishVO> listWithFlavor(DishDTO dto) {
        Map<String, Object> build = MapUtils.builder()
                .field(DishVO::getCategoryId,dto.getCategoryId()).op(Equal.class)
                .field(DishVO::getStatus,StatusConstant.ENABLE).op(Equal.class)
                .orderBy(DishVO::getCreateTime).desc()
                .build();
        List<DishVO> dishVOS = beanSearcher.searchAll(DishVO.class, build);
        if (!CollectionUtils.isEmpty(dishVOS)){
            dishVOS.forEach(item ->{
                Map<String, Object> build1 = MapUtils.builder()
                        .field(DishFlavor::getDishId,item.getId()).op(Equal.class)
                        .build();
                List<DishFlavor> dishFlavors = beanSearcher.searchAll(DishFlavor.class, build1);
                item.setFlavors(dishFlavors);
            });
        }
        return dishVOS;
    }

    @Override
    public DishVO selectDishById(Long id) {
        Map<String, Object> build = MapUtils.builder()
                .field(DishVO::getId,id).op(Equal.class)
                .build();
        DishVO dishVO = beanSearcher.searchFirst(DishVO.class, build);
        if(Objects.nonNull(dishVO)){
            String cover = dishVO.getCover();
            if (StringUtils.isNotEmpty(cover)){
                Attachment attachment = attachmentMapper.selectById(cover);
                dishVO.setAttachment(attachment);
            }
        }

        Map<String, Object> build1 = MapUtils.builder()
                .field(DishFlavor::getDishId,id).op(Equal.class)
                .build();
        List<DishFlavor> dishFlavors = beanSearcher.searchAll(DishFlavor.class, build1);
        dishVO.setFlavors(dishFlavors);
        return dishVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertDish(DishDTO dto) {
        final int[] result = {0};
        Dish dish = new Dish();
        BeanCopyUtil.copyProperties(dto,dish);
        List<File> files = dto.getFiles();
        if(!CollectionUtils.isEmpty(files)) {
            String fileId = fileCommon.saveFiles(files);
            dish.setCover(fileId);
        }
        dish.setStatus(StatusConstant.DISABLE);
        dish.setCreateBy(BaseContext.getCurrentName());
        dish.setCreateTime(DateUtils.getNowDate());
        dish.setUpdateBy(BaseContext.getCurrentName());
        dish.setUpdateTime(DateUtils.getNowDate());
        result[0] = result[0] + dishMapper.insert(dish);

        List<DishFlavor> flavors = dto.getFlavors();
        if(!CollectionUtils.isEmpty(flavors)){
            flavors.forEach(item->{
                item.setDishId(dish.getId());
                item.setCreateBy(BaseContext.getCurrentName());
                item.setCreateTime(DateUtils.getNowDate());
                item.setUpdateBy(BaseContext.getCurrentName());
                item.setUpdateTime(DateUtils.getNowDate());
                result[0] = result[0] + dishFlavorMapper.insert(item);
            });
        }

        return result[0];
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDish(DishDTO dto) {
        int result = 0;
        Dish dish = new Dish();
        BeanCopyUtil.copyProperties(dto,dish);
        List<File> files = dto.getFiles();
        if(!CollectionUtils.isEmpty(files)) {
            String fileId = fileCommon.saveFiles(files);
            dish.setCover(fileId);
        }
        dish.setUpdateBy(BaseContext.getCurrentName());
        dish.setUpdateTime(DateUtils.getNowDate());
        result = dishMapper.updateById(dish);

        List<DishFlavor> flavors = dto.getFlavors();
        if(!CollectionUtils.isEmpty(flavors)){

            List<Long> idList = flavors.stream().map(DishFlavor::getId).filter(id -> id > 0).toList();
            dishFlavorMapper.deleteBatchIds(idList);

            flavors.forEach(item->{
                item.setDishId(dish.getId());
                item.setCreateBy(BaseContext.getCurrentName());
                item.setCreateTime(DateUtils.getNowDate());
                item.setUpdateBy(BaseContext.getCurrentName());
                item.setUpdateTime(DateUtils.getNowDate());
                dishFlavorMapper.insert(item);
            });
        }else {
            //删除
            Map<String, Object> build = MapUtils.builder()
                    .field(DishFlavor::getDishId,dto.getId()).op(Equal.class)
                    .build();
            List<DishFlavor> dishFlavors = beanSearcher.searchAll(DishFlavor.class, build);
            List<Long> idList = dishFlavors.stream().map(DishFlavor::getId).filter(id -> id > 0).toList();
            dishFlavorMapper.deleteBatchIds(idList);
        }
        return result;
    }

    /**
     * 修改菜品状态
     * @param dto 菜品信息
     * @return
     */
    @Override
    public int updateDishStatus(DishDTO dto) {
        Dish dish = new Dish();
        BeanCopyUtil.copyProperties(dto,dish);
        dish.setUpdateBy(BaseContext.getCurrentName());
        dish.setUpdateTime(DateUtils.getNowDate());
        return dishMapper.updateById(dish);
    }

    /**
     * 删除菜品
     * @param ids id集合
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteDishByIds(Long[] ids) {
        int result = 0;

        //判断当前菜品是否起售状态，起售状态不能删除
        Map<String, Object> build = MapUtils.builder()
                .field(Dish::getId, Arrays.asList(ids)).op(InList.class)
                .build();
        List<Dish> dishes = beanSearcher.searchAll(Dish.class, build);
        if (!CollectionUtils.isEmpty(dishes)){
            dishes.forEach(item->{
                Integer status = item.getStatus();
                if (Objects.equals(status, StatusConstant.ENABLE)){
                    //当前菜品处于起售状态不能删除
                    throw new ServiceException(MessageConstant.DISH_ON_SALE);
                }
            });
        }

        //判断当前彩屏是否关联的套餐，关联了套餐不能删除
        Map<String, Object> build1 = MapUtils.builder()
                .field(SetmealDish::getDishId,Arrays.asList(ids)).op(InList.class)
                .build();
        int i = beanSearcher.searchCount(SetmealDish.class, build1).intValue();
        if (i > 0){
            //当前菜品有关联的套餐，不能删除
            throw new ServiceException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }


        //删除菜品数据
        UpdateWrapper<DishFlavor> wrapper = new UpdateWrapper<>();
        wrapper.in("dish_id",(Object[]) ids);
        wrapper.set("del_flag","2");
        wrapper.set("update_time", DateUtils.getNowDate());
        wrapper.set("update_by", BaseContext.getCurrentName());
        result = result + dishFlavorMapper.update(null,wrapper);

        //删除菜品数据
        UpdateWrapper<Dish> wrapper1 = new UpdateWrapper<>();
        wrapper1.in("id",(Object[]) ids);
        wrapper1.set("del_flag","2");
        wrapper1.set("update_time", DateUtils.getNowDate());
        wrapper1.set("update_by", BaseContext.getCurrentName());
        result = result + dishMapper.update(null,wrapper1);

        return result;
    }
}
